﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using AAA.Base.Util;

namespace AAA.Web
{
    public class HtmlPageDownloader
    {
        private const int BUFFER_SIZE = 4096;
        private WebClient _webClient;
        private string _strMessage;
        private string _strSavePath;
        private string _strPath;
        private FileTypeEnum _eFileType;

        public HtmlPageDownloader()
        {
            _webClient = new WebClient();
            _eFileType = FileTypeEnum.asc;
            _webClient.Headers.Add("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*");
            _webClient.Headers.Add("Accept-Language", "zh-TW");
            _webClient.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");            
        }

        public string Path
        {
            get { return _strPath; }
            set { _strPath = value; }
        }

        public string Message
        {
            get { return _strMessage; }
        }

        public FileTypeEnum FileType
        {
            get { return _eFileType; }
            set { _eFileType = value; }
        }

        public string ParseParameter(string strFormat, object oValue)
        {
            try
            {
                string strParameter;
                string strType;
                string strDataFormat;
                string strValue = "";
                int iStart;
                int iEnd;

                iStart = strFormat.IndexOf('{');
                iEnd = strFormat.IndexOf('}', iStart + 1);

                strParameter = strFormat.Substring(iStart + 1, iEnd - iStart - 1);

                strType = strParameter.Split(':')[0];
                strDataFormat = strParameter.Split(':')[1];
                
                switch (strType.ToLower())
                {
                    case "date":
                        strValue = ((DateTime)oValue).ToString(strDataFormat);
                        break;
                    case "datetw":
                        int iIndex = 0;

                        while (iIndex < strDataFormat.Length && strDataFormat[iIndex] == 'y')
                            iIndex++;

                        strValue = (((DateTime)oValue).Year - 1911).ToString(strDataFormat.Substring(0, iIndex).Replace('y', '0'));

                        if (iIndex < strDataFormat.Length)
                            strValue = strValue + ((DateTime)oValue).ToString(strDataFormat.Substring(iIndex));
                        break;
                    case "now":
                        strValue = DateTime.Now.ToString(strDataFormat);
                        break;
                    case "int":
                        strValue = ((int)oValue).ToString(strDataFormat);
                        break;
                    case "string":
                        strValue = (string)oValue;
                        break;
                }

                return strFormat.Substring(0, iStart) + strValue + strFormat.Substring(iEnd + 1);
            }
            catch (Exception ex)
            {
                _strMessage = "-E- " + ex.Message + "," + ex.StackTrace;
            }
            return strFormat;
        }

        public void DownloadPages(string strUrl, string strFilename, List<object> lstParameter)
        {
            DownloadPages(strUrl, strFilename, lstParameter, Encoding.Default);
        }

        public void DownloadPages(string strUrl, string strFilename, List<object> lstParameter, Encoding encoding)
        {
            DownloadPages(strUrl, strFilename, lstParameter, encoding, encoding);
        }

        public void DownloadPages(string strUrl, string strFilename, List<object> lstParameter, Encoding encoding, Encoding convertEncoding)
        {
            string strParsedUrl;
            string strParsedFilename;

            foreach (object oParameter in lstParameter)
            {
                strParsedUrl = strUrl;
                strParsedFilename = strFilename;

                _strSavePath = Path;

                while(_strSavePath.IndexOf('{') > -1)
                    _strSavePath = ParseParameter(_strSavePath, oParameter);

                while (strParsedUrl.IndexOf('{') > -1)
                    strParsedUrl = ParseParameter(strParsedUrl, oParameter);

                while (strParsedFilename.IndexOf('{') > -1)
                    strParsedFilename = ParseParameter(strParsedFilename, oParameter);

                //DownloadPage(strParsedUrl, strParsedFilename);
                DownloadPage(strParsedUrl, strParsedFilename,encoding, convertEncoding);
            }
        }

        public bool DownloadPage(string strUrl, string strFilename)
        {
            return DownloadPage(strUrl, strFilename, Encoding.Default);
        }

        public bool DownloadPage(string strUrl, string strFilename, Encoding encoding)
        {
            return DownloadPage(strUrl, strFilename, encoding, encoding);
        }

        
        public bool DownloadPage(string strUrl, string strFilename, Encoding encoding, Encoding convertEncoding)
        {
            StreamWriter sw = null;
            StreamReader sr = null;

            BinaryWriter bw = null;
            BinaryReader br = null;            

            Stream s = null;
            byte[] bBuffer = new byte[BUFFER_SIZE];
            int iLength;
            string strFullFilename;
            string strHtml;
            bool isSuccess = false;

            try
            {
                if (_strSavePath == null)
                    _strSavePath = Path;

                if (Directory.Exists(_strSavePath) == false)
                    Directory.CreateDirectory(_strSavePath);
               
                s = _webClient.OpenRead(strUrl);
                strFullFilename = _strSavePath + @"\" + strFilename;
                switch (FileType)
                {
                    case FileTypeEnum.asc:                        
                       
                        sr = new StreamReader(s,encoding);
                        
                        sw = new StreamWriter(strFullFilename, false, convertEncoding);
                        strHtml = sr.ReadToEnd();

                        if (encoding != convertEncoding)
                            strHtml = convertEncoding.GetString(Encoding.Convert(encoding, convertEncoding, encoding.GetBytes(strHtml)));
                            //strHtml = StringHelper.CharSetConvert(strHtml, encoding, convertEncoding);

                        sw.Write(strHtml);
                        break;

                    case FileTypeEnum.bin:
                        br = new BinaryReader(s, encoding);
                        bw = new BinaryWriter(new FileStream(strFullFilename, FileMode.Create), convertEncoding);


                        while ((iLength = br.Read(bBuffer, 0, BUFFER_SIZE)) != 0)
                            bw.Write(bBuffer, 0, iLength);
                        break;
                }

                _strMessage = "-I- Download " + strUrl + " completed";
                isSuccess = true;
            }
            catch (Exception ex)
            {
                _strMessage = "-E- " + ex.Message + "," + ex.StackTrace;
            }
            finally
            {
                if (sr != null)
                    sr.Close();

                if (br != null)
                    br.Close();

                if (s != null)
                    s.Close();

                if (sw != null)
                    sw.Close();

                if (bw != null)
                    bw.Close();
            }

            return isSuccess;
        }
    }
}